package com.cip.admin.service.impl;

import com.cip.admin.dao.UserDao;
import com.cip.admin.model.Institute;
import com.cip.admin.model.User;
import com.cip.admin.service.impl.GenericManagerImpl;

import org.acegisecurity.providers.encoding.PasswordEncoder;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.cip.admin.service.InstituteService;
import com.cip.admin.service.UserExistsException;
import com.cip.admin.service.UserManager;
import com.cip.admin.service.UserService;
import com.cip.common.util.CommonUtil;
import com.cip.common.util.GridUtil;
import com.cip.master.model.Academic;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;


/**
 * Implementation of UserManager interface.
 *
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
 */
public class UserManagerImpl extends GenericManagerImpl<User, Integer> implements UserManager, UserService {
    private PasswordEncoder passwordEncoder;
    private UserDao userDao;
    private InstituteService instituteService;
    private VelocityEngine velocityEngine;

    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    public void setUserDao(UserDao userDao) {
        this.dao = userDao;
        this.userDao = userDao;
    }

    /**
     * {@inheritDoc}
     */
    public User getUser(String userId) {
        return userDao.get(new Integer(userId));
    }

    /**
     * {@inheritDoc}
     */
    public List<User> getUsers() {
        return userDao.getUsers();
    }

    public VelocityEngine getVelocityEngine() {
		return velocityEngine;
	}

	public void setVelocityEngine(VelocityEngine velocityEngine) {
		this.velocityEngine = velocityEngine;
	}

	/**
     * {@inheritDoc}
     */
    public User saveUser(User user) throws UserExistsException{
    	Calendar cal = Calendar.getInstance();
    	//  System.out.println("current ate------------------->"+dateFormat.format(cal.getTime()));
    	user.setCreateDate(cal.getTime());
    	 //set the username for student
        if(user.getUsername() == null){
        	//DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
     	    //get current date time with Calendar()
     	   
     	   try{
     		   Institute institute = instituteService.getInstituteById(user.getTenantId());
     		   int lastId = userDao.getLastCandidateId(Integer.valueOf(user.getClassYear()), Integer.valueOf(user.getSection()));
     		   System.out.println("last id---------->"+lastId);
     		   String username = institute.getPrefix()+cal.get(Calendar.YEAR)+(lastId+1);
     		   System.out.println("last id---------->"+username);
     		   user.setUsername(username);
     		   user.setPassword(username);     		   
     	   } catch (Exception e) {
   			e.printStackTrace();
     	   }
        	
        }
        
       /* if (user.getVersion() == null) {
            // if new user, lowercase userId
            user.setUsername(user.getUsername().toLowerCase());
        }*/
       
        //default profile image path
        if(user.getProfilePath() == null || user.getProfilePath() == ""){
    		user.setProfilePath("/images/cip/user/default/user-default.gif");
    	}
        // Get and prepare password management-related artifacts
        boolean passwordChanged = false;
        if (passwordEncoder != null) {
            // Check whether we have to encrypt (or re-encrypt) the password
            if (user.getVersion() == null) {
                // New user, always encrypt
                passwordChanged = true;
            } else {
                // Existing user, check password in DB
                String currentPassword = userDao.getUserPassword(user.getUsername());
                if (currentPassword == null) {
                    passwordChanged = true;
                } else {
                    if (!currentPassword.equals(user.getPassword())) {
                        passwordChanged = true;
                    }
                }
            }

            // If password was changed (or new user), encrypt it
            if (passwordChanged) {
                user.setPassword(passwordEncoder.encodePassword(user.getPassword(), null));
            }
        } else {
            log.warn("PasswordEncoder not set, skipping password encryption...");
        }

        try {
        	System.out.println("In maggr"+user.toString());
            return userDao.saveUser(user);
        } catch (DataIntegrityViolationException e) {
            //e.printStackTrace();
            log.warn(e.getMessage());
            throw new UserExistsException("User '" + user.getUsername() + "' already exists!");
        } catch (JpaSystemException e) { // needed for JPA
            //e.printStackTrace();
            log.warn(e.getMessage());
            throw new UserExistsException("User '" + user.getUsername() + "' already exists!");
        }
    }
    
    public String getCandidateGridList(Locale locale)throws Exception {
		
		String gridSource = ""; 
		
		try {
			List<User> userList = getAllCandidates();
			
			List<Map<String,Object>> userArrayList = new ArrayList<Map<String,Object>>();
			
			System.out.println("instList============="+userList);
			
			for (User user : userList) {
				Map<String,Object> userObj = new HashMap<String, Object>();
				userObj.put("username", "<a href='/editCandidate?method=editCandidate&id="+user.getId()+"' style='text-decoration:underline;color:blue;'>"+user.getUsername()+"</a>");
				userObj.put("fullName", user.getFullName());
				userObj.put("email", user.getEmail());
				userObj.put("status", user.getStatus());
				
				System.out.println("userObj================"+userObj);
				
				userArrayList.add(userObj);			
			}
			
			System.out.println("userArrayList=========="+userArrayList);
			
			gridSource = generateScriptForProcess(velocityEngine, userArrayList, locale);
			
			System.out.println("gridSource===================="+gridSource);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return gridSource;
	}
    
    /** Set into context of grid column names and field names and it attributes
	 * 
	 * @param context
	 * @return
	 * @throws Exception
	 */
	public static String generateScriptForProcess(VelocityEngine velocityEngine, List<Map<String, Object>> userArrayList, Locale locale) throws Exception {
		
		System.out.println("instArrayList========="+userArrayList);
		System.out.println("locale========="+locale);

		return GridUtil.generateScriptForProcess(velocityEngine, userArrayList, createUserGridColumnMapping(locale));
		
	}
	
	/**
	 * Add needed column and it mapping for my instances
	 * 
	 * @param context
	 */
	private static Map<String, Object> createUserGridColumnMapping(Locale locale) {
		Map<String, Object> context = new HashMap<String, Object>();
		List<Map<String, Object>> fieldNameList = new ArrayList<Map<String, Object>>();
		//ResourceBundle appResourceBundle = ResourceBundle.getBundle(Constants.BUNDLE_KEY ,locale);
		//context.put("title", appResourceBundle.getString("process.myInstances"));
		context.put("title", "User List");
		context.put("gridId", "MY_USERLIST");
		context.put("needTreeStructure", true);
		//context.put("dynamicGridWidth", "300px");
		//context.put("dynamicGridHeight", "580px");
		String columnNames = "['User Name','Full Name','Email','Status']";
        CommonUtil.createFieldNameList(fieldNameList, "username", "100", "center", "","false");
        CommonUtil.createFieldNameList(fieldNameList, "fullName", "100", "left","", "false");
        CommonUtil.createFieldNameList(fieldNameList, "email", "100","left", "", "false");
        CommonUtil.createFieldNameList(fieldNameList, "status", "70", "center", "", "false");

        context.put("columnNames", columnNames);
        context.put("noOfRecords", "10");
		context.put("fieldNameList", fieldNameList);
		context.put("gridHeading", "true");
		
		System.out.println("context====================="+context);
		
		return context;
	}

    /**
     * {@inheritDoc}
     */
    public void removeUser(String userId) {
        log.debug("removing user: " + userId);
        userDao.remove(new Integer(userId));
    }

    /**
     * {@inheritDoc}
     *
     * @param username the login name of the human
     * @return User the populated user object
     * @throws UsernameNotFoundException thrown when username not found
     */
    public User getUserByUsername(String username) throws Exception {
        return (User) userDao.loadUserByUsername(username);
    }

    /**
     * {@inheritDoc}
     */
    public List<User> search(String searchTerm) {
        return super.search(searchTerm, User.class);
    }
    
    /**
     * {@inheritDoc}
     */
    public List<User> getAllUsers() {
        return userDao.getAll();
    }
    
    public List<User> getAllCandidates() throws Exception{
    	return userDao.getAllCandidates();
    }
    
    public User saveOrUpdateUser(User user) throws Exception{
    	return userDao.saveOrUpdateUser(user);
    }
    
    public List<User> getAllCandidatesByClass(int classId, int sectionId) throws Exception{
    	return userDao.getAllCandidatesByClass(classId, sectionId);
    	
    }

	public InstituteService getInstituteService() {
		return instituteService;
	}

	public void setInstituteService(InstituteService instituteService) {
		this.instituteService = instituteService;
	}   
    
    
}
